/*NOTICE

This software was produced for the U. S. Government
under Contract No. FA8721-09-C-0002, and is
subject to the Rights in Noncommercial Computer Software
and Noncommercial Computer Software Documentation Clause
(DFARS) 252.227-7014 (JUN 1995)

(c) 2009 The MITRE Corporation. All Rights Reserved.
*/
package org.mitre.xmltransform.spmif;

import java.io.File;
import java.util.HashMap;
import java.util.Map;

import org.mitre.xmltransform.XmlOutputDocument;
import org.w3c.dom.Attr;
import org.w3c.dom.Element;

public class SpmifOutputDocument extends XmlOutputDocument {
	public SpmifOutputDocument(File pOutputFile) {
		super(pOutputFile);
		mLocations = new HashMap<String, Device>();
	}
	
	public void createProjectElement(String pName) {
		mProjectElement = addRootElement("Project", null);
		mProjectElement.setAttribute("Project_Name", pName);		

		Attr schemaAttrib = createAttributeNS("http://www.w3.org/2001/XMLSchema-instance", "noNamespaceSchemaLocation");
		schemaAttrib.setPrefix("xsi");
		schemaAttrib.setValue("s-pmifschema.xsd");
		mProjectElement.setAttributeNodeNS(schemaAttrib);
	}
	
	public Element createPerformanceScenario(String pName, String pFileName, String pInterarrivalTime, String pInterarrivalTimeUnits, String pPriority) {
		Element perfScenarioElem = addElement(mProjectElement, "PerformanceScenario", null);
		perfScenarioElem.setAttribute("NumberOfJobs", "1");
		perfScenarioElem.setAttribute("InterarrivalTime", (pInterarrivalTime == null) ? "0.0" : pInterarrivalTime);
		perfScenarioElem.setAttribute("InterarrivalTimeUnits", (pInterarrivalTimeUnits == null) ? "ms" : pInterarrivalTimeUnits);
		perfScenarioElem.setAttribute("SWmodelfilename", pFileName);
		perfScenarioElem.setAttribute("ScenarioName", pName);
		if (pPriority != null && pPriority.length() > 0) {
			perfScenarioElem.setAttribute("Priority", pPriority);
		}
		return perfScenarioElem;
	}

	public Element createExecutionGraph(Element pPerfScenarioElement, String pId, String pName, boolean pIsMain) {
		Element execGraphElem = addElement(pPerfScenarioElement, "ExecutionGraph", null);
		execGraphElem.setAttribute("EGname", pName);
		execGraphElem.setAttribute("IsMainEG", pIsMain ? "true" : "false");
		//String id = this.getNextId();
		//execGraphElem.setAttribute("EGId", id);
		//pPerfScenarioElement.setAttribute("EGId", id);
		String id = (pId == null) ? pName : pId;
		execGraphElem.setAttribute("EGId", id);
		if (pIsMain) {
			pPerfScenarioElement.setAttribute("EGId", id);
		}
		return execGraphElem;
	}
	
	public void finishDocument() {
		Element sr, dev;
		Device d;
		
		Element po = addElement(mProjectElement, "ProcessingOverhead", null);
		Element srs = addElement(po, "SoftwareResources", null);
		for (String location : mLocations.keySet()) {
			d = mLocations.get(location);
			sr = addElement(srs, "SoftwareResource", null);
			sr.setAttribute("ResourceName", d.getType());
			sr.setAttribute("ResourceID", "R" + d.getName());
		}
		Element devs = addElement(po, "Devices", null);
		for (String location : mLocations.keySet()) {
			d = mLocations.get(location);
			dev = addElement(devs, "Device", null);
			dev.setAttribute("DeviceID", "D" + d.getName());
			dev.setAttribute("DeviceName", d.getType());
			dev.setAttribute("DeviceFeature", "NonFCFSDemandSpec");
			dev.setAttribute("Quantity", "" + d.getQuantity());
			if (d != null && d.getSchedulingPolicy() != null) {
				dev.setAttribute("SchedulingPolicy", d.getSchedulingPolicy());
			} else {
				dev.setAttribute("SchedulingPolicy", "PS");
			}
			dev.setAttribute("ServiceUnits", "ms");
			dev.setAttribute("ServiceTime", "1");
		}
		
		Element ohm = addElement(po, "OverheadMatrix", null);
		for (String location : mLocations.keySet()) {
			d = mLocations.get(location);
			Element ome = addElement(ohm, "OMElement", null);
			ome.setAttribute("ResourceID", "R" + d.getName());
			ome.setAttribute("DeviceID", "D" + d.getName());
			ome.setAttribute("AmountOfService", "1");
		}
	}
	
	public void registerLocation(Device pLocation) {
		if (pLocation == null) {
			pLocation = new Device("Default", Device.TYPE_PROCESSING, "PS", 1);
		}
		if (!mLocations.containsKey(pLocation.getName())) {
			mLocations.put(pLocation.getName(), pLocation);
		}
	}

	private Map<String, Device> mLocations;
	private Element mProjectElement;
}
